package com.mia.props.common.entities;

import com.mia.craftstudio.minecraft.CraftStudioRendererVBO;
import com.mia.craftstudio.minecraft.DirectionHelper;
import com.mia.craftstudio.minecraft.INodeProvider;
import com.mia.craftstudio.minecraft.ImmutableDirectionHolder;
import com.mia.props.common.TileProps;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.util.ForgeDirection;

import static com.mia.craftstudio.minecraft.PortUtils.getDirectionFromFacing;
import static com.mia.craftstudio.minecraft.PortUtils.getDirectionsFromFacing;

public class TileVariableRendering extends TileProps implements INodeProvider {
   private Map filtersFILLED_Pos = new HashMap();
   private Map filtersEMPTY_Pos = new HashMap();
   private Map filtersFILLED_Neg = new HashMap();
   private Map filtersEMPTY_Neg = new HashMap();
   private Map filtersCorner_Pos = new HashMap();
   private Map filtersCorner_Neg = new HashMap();
   private Map filtersDouble_Pos = new HashMap();
   private Map filtersDouble_Neg = new HashMap();
   private String statusHash;
   private final int[] rotations = new int[]{2, 1, 0, 3};

   private Map getSurroundingProps() {
      Map outMap = new HashMap();
      Iterator var2 = DirectionHelper.directions.iterator();

      while(true) {
         ImmutableDirectionHolder fd;
         TileEntity te;
         do {
            if (!var2.hasNext()) {
               return outMap;
            }

            fd = (ImmutableDirectionHolder)var2.next();
            int[] offset = fd.getOffset();
            te = this.worldObj.getTileEntity(this.xCoord + offset[0], this.yCoord + offset[1], this.zCoord + offset[2]);
         } while(!this.sameID(te));

         String key = "";
         EnumFacing[] var7 = fd.getDirections();
         int var8 = var7.length;

         for(int var9 = 0; var9 < var8; ++var9) {
            EnumFacing enumFacing = var7[var9];
            key = key + this.correctOrientation(getDirectionFromFacing(enumFacing)).toString().substring(0, 1);
         }

         outMap.put(DirectionHelper.getDirection(key), (TileProps)te);
      }
   }

   public String getParam(String key) {
      return (String)this.getModelData().tileParams.get(key);
   }

   public String getStatusHash() {
      if (this.worldObj == null) {
         return null;
      } else {
         if (this.statusHash == null) {
            Map props = this.getSurroundingProps();
            this.statusHash = String.format("%d:", this.rotation);

            EnumSet dirs;
            for(Iterator var2 = props.keySet().iterator(); var2.hasNext(); this.statusHash = this.statusHash + dirs.toString() + ",") {
               dirs = (EnumSet)var2.next();
            }
         }

         return this.statusHash;
      }
   }

   private ForgeDirection correctOrientation(ForgeDirection fdi) {
      ForgeDirection fdo = fdi;

      for(int i = 0; i < this.rotations[this.rotation / 4]; ++i) {
         fdo = fdo.getRotation(ForgeDirection.DOWN);
      }

      return fdo;
   }

   private void markSurroundingDirty() {
      if (this.worldObj != null) {
         Iterator var1 = this.getSurroundingProps().values().iterator();

         while(var1.hasNext()) {
            TileProps tile = (TileProps)var1.next();
            if (tile != null) {
               tile.markRenderDirty();
            }
         }

      }
   }

   public void markRenderDirty() {
      this.statusHash = null;
      super.markRenderDirty();
   }

   public void invalidate() {
      this.markSurroundingDirty();
      super.invalidate();
   }

   private void parsePatterns(String rules, Map pos, Map neg, Object index) {
      List patternsPos = new ArrayList();
      List patternsNeg = new ArrayList();
      String[] var7 = rules.split(";");
      int var8 = var7.length;

      for(int var9 = 0; var9 < var8; ++var9) {
         String s = var7[var9];
         String pattern = s.replace(".", "\\.").replace("*", "*.").replace("?", ".");
         if (!pattern.startsWith("!")) {
            patternsPos.add(Pattern.compile(pattern));
         } else {
            patternsNeg.add(Pattern.compile(pattern.substring(1)));
         }
      }

      pos.put(index, patternsPos);
      neg.put(index, patternsNeg);
   }

   public void readFromNBT(NBTTagCompound compound) {
      super.readFromNBT(compound);
      this.init();
   }

   public void init() {
      if (!this.initialized) {
         ForgeDirection[] var1 = getDirectionsFromFacing(DirectionHelper.flatDirections);
         int var2 = var1.length;

         int var3;
         ForgeDirection fd1o;
         for(var3 = 0; var3 < var2; ++var3) {
            fd1o = var1[var3];
            ForgeDirection fd = this.correctOrientation(fd1o);
            this.filtersFILLED_Pos.put(fd, new ArrayList());
            this.filtersFILLED_Neg.put(fd, new ArrayList());
            this.filtersEMPTY_Pos.put(fd, new ArrayList());
            this.filtersEMPTY_Neg.put(fd, new ArrayList());
            String baseKey = "Nodes_" + fd1o.toString();
            String keyFILLED = baseKey + "_FILLED";
            String keyEMPTY = baseKey + "_EMPTY";
            Iterator var9 = this.getModelData().tileParams.keySet().iterator();

            while(var9.hasNext()) {
               String k = (String)var9.next();
               if (k.toLowerCase().equals(keyFILLED.toLowerCase())) {
                  this.parsePatterns((String)this.getModelData().tileParams.get(k), this.filtersFILLED_Pos, this.filtersFILLED_Neg, fd);
               }

               if (k.toLowerCase().equals(keyEMPTY.toLowerCase())) {
                  this.parsePatterns((String)this.getModelData().tileParams.get(k), this.filtersEMPTY_Pos, this.filtersEMPTY_Neg, fd);
               }
            }
         }

         var1 = getDirectionsFromFacing(DirectionHelper.flatDirections);
         var2 = var1.length;

         String key;
         Iterator var12;
         String k;
         ForgeDirection[] var14;
         int var15;
         int var16;
         ForgeDirection fd2o;
         ForgeDirection fd1;
         ForgeDirection fd2;
         for(var3 = 0; var3 < var2; ++var3) {
            fd1o = var1[var3];
            var14 = getDirectionsFromFacing(DirectionHelper.flatDirections);
            var15 = var14.length;

            for(var16 = 0; var16 < var15; ++var16) {
               fd2o = var14[var16];
               if (!fd1o.equals(fd2o)) {
                  fd1 = this.correctOrientation(fd1o);
                  fd2 = this.correctOrientation(fd2o);
                  this.filtersDouble_Pos.put(EnumSet.of(fd1, fd2), new ArrayList());
                  this.filtersDouble_Neg.put(EnumSet.of(fd1, fd2), new ArrayList());
                  key = "Nodes_" + fd1o.toString().charAt(0) + fd2o.toString().charAt(0) + "_DOUBLE";
                  var12 = this.getModelData().tileParams.keySet().iterator();

                  while(var12.hasNext()) {
                     k = (String)var12.next();
                     if (k.toLowerCase().equals(key.toLowerCase())) {
                        this.parsePatterns((String)this.getModelData().tileParams.get(k), this.filtersDouble_Pos, this.filtersDouble_Neg, EnumSet.of(fd1, fd2));
                     }
                  }
               }
            }
         }

         var1 = new ForgeDirection[]{ForgeDirection.NORTH, ForgeDirection.SOUTH};
         var2 = var1.length;

         for(var3 = 0; var3 < var2; ++var3) {
            fd1o = var1[var3];
            var14 = new ForgeDirection[]{ForgeDirection.EAST, ForgeDirection.WEST};
            var15 = var14.length;

            for(var16 = 0; var16 < var15; ++var16) {
               fd2o = var14[var16];
               fd1 = this.correctOrientation(fd1o);
               fd2 = this.correctOrientation(fd2o);
               this.filtersCorner_Pos.put(EnumSet.of(fd1, fd2), new ArrayList());
               this.filtersCorner_Neg.put(EnumSet.of(fd1, fd2), new ArrayList());
               key = "Nodes_" + fd1o.toString().charAt(0) + fd2o.toString().charAt(0) + "_CORNER";
               var12 = this.getModelData().tileParams.keySet().iterator();

               while(var12.hasNext()) {
                  k = (String)var12.next();
                  if (k.toLowerCase().equals(key.toLowerCase())) {
                     this.parsePatterns((String)this.getModelData().tileParams.get(k), this.filtersCorner_Pos, this.filtersCorner_Neg, EnumSet.of(fd1, fd2));
                  }
               }
            }
         }

         this.markSurroundingDirty();
         this.initialized = true;
      }

   }

   @SideOnly(Side.CLIENT)
   public Set getNodes(Set inNodes) {
      Set outNodes = new HashSet();
      Set filtersPos = new HashSet();
      Set filtersNeg = new HashSet();
      Map tiles = this.getSurroundingProps();
      ForgeDirection[] var6 = getDirectionsFromFacing(DirectionHelper.flatDirections);
      int var7 = var6.length;

      int var8;
      ForgeDirection fd1;
      for(var8 = 0; var8 < var7; ++var8) {
         fd1 = var6[var8];
         if (tiles.containsKey(EnumSet.of(fd1))) {
            filtersPos.addAll((Collection)this.filtersFILLED_Pos.get(fd1));
            filtersNeg.addAll((Collection)this.filtersFILLED_Neg.get(fd1));
         } else {
            filtersPos.addAll((Collection)this.filtersEMPTY_Pos.get(fd1));
            filtersNeg.addAll((Collection)this.filtersEMPTY_Neg.get(fd1));
         }
      }

      var6 = getDirectionsFromFacing(DirectionHelper.flatDirections);
      var7 = var6.length;

      ForgeDirection[] var10;
      int var11;
      int var12;
      ForgeDirection fd2;
      for(var8 = 0; var8 < var7; ++var8) {
         fd1 = var6[var8];
         var10 = getDirectionsFromFacing(DirectionHelper.flatDirections);
         var11 = var10.length;

         for(var12 = 0; var12 < var11; ++var12) {
            fd2 = var10[var12];
            if (!fd1.equals(fd2) && tiles.containsKey(EnumSet.of(fd1)) && tiles.containsKey(EnumSet.of(fd2))) {
               filtersPos.addAll((Collection)this.filtersDouble_Pos.get(EnumSet.of(fd1, fd2)));
               filtersNeg.addAll((Collection)this.filtersDouble_Neg.get(EnumSet.of(fd1, fd2)));
            }
         }
      }

      var6 = new ForgeDirection[]{ForgeDirection.NORTH, ForgeDirection.SOUTH};
      var7 = var6.length;

      for(var8 = 0; var8 < var7; ++var8) {
         fd1 = var6[var8];
         var10 = new ForgeDirection[]{ForgeDirection.EAST, ForgeDirection.WEST};
         var11 = var10.length;

         for(var12 = 0; var12 < var11; ++var12) {
            fd2 = var10[var12];
            if (tiles.containsKey(EnumSet.of(fd1)) && tiles.containsKey(EnumSet.of(fd2)) && tiles.containsKey(EnumSet.of(fd1, fd2))) {
               filtersPos.addAll((Collection)this.filtersCorner_Pos.get(EnumSet.of(fd1, fd2)));
               filtersNeg.addAll((Collection)this.filtersCorner_Neg.get(EnumSet.of(fd1, fd2)));
            }
         }
      }

      Iterator var14 = inNodes.iterator();

      while(var14.hasNext()) {
         CraftStudioRendererVBO node = (CraftStudioRendererVBO)var14.next();
         String name = node.getNode().getFullName();
         Iterator var18 = filtersPos.iterator();

         while(var18.hasNext()) {
            Pattern p = (Pattern)var18.next();
            if (p.matcher(name).find()) {
               outNodes.add(node);
            }
         }
      }

      CraftStudioRendererVBO[] var15 = (CraftStudioRendererVBO[])outNodes.toArray(new CraftStudioRendererVBO[0]);
      var7 = var15.length;

      for(var8 = 0; var8 < var7; ++var8) {
         CraftStudioRendererVBO node = var15[var8];
         String name = node.getNode().getFullName();
         Iterator var22 = filtersNeg.iterator();

         while(var22.hasNext()) {
            Pattern p = (Pattern)var22.next();
            if (p.matcher(name).find()) {
               outNodes.remove(node);
            }
         }
      }

      return outNodes;
   }
}
